/*****************************************************************************/
/*                                                                           */
/*    Domino Operation System Driver Module                                  */
/*                                                                           */
/*    Copyright (C) 2008 Laszlo Arvai                                        */
/*                                                                           */
/*    ------------------------------------------------------------------     */
/*    SPI Driver for PIC32 series                                            */
/*****************************************************************************/

///////////////////////////////////////////////////////////////////////////////
// Includes
#include <peripheral/spi.h>
#include "_spi_map_tbl.h"
#include <drvSPI.h>
#include "drvIOConfig.h"

/*****************************************************************************/
/* SPI 1 Functions                                                           */
/*****************************************************************************/

///////////////////////////////////////////////////////////////////////////////
// Initialize SPI driver
#if defined(drvSPI1_CONF) && defined(drvSPI1_BAUD)
void drvSPI1Init(void)
{
	SPI1CON = drvSPI1_CONF; // select mode and enable SPI1
	SPI1BRG = drvSPI1_BAUD; // select clock speed
}

///////////////////////////////////////////////////////////////////////////////
// Send and receive one byte over SPI interface
dosByte drvSPI1SendAndReceiveByte( dosByte in_byte )
{
	SPI1BUF = in_byte;						// write to buffer for TX
	while ( !SPI1STATbits.SPIRBF);	// wait for transfer complete
	return SPI1BUF;								// read the received value
}

///////////////////////////////////////////////////////////////////////////////
// Sets a new baud rate
void drvSPI1SetBaudRate(dosDWord in_baud_rate)
{
	SPI1BRG = SpiBrgVal(sysPBCLK_FREQUENCY, in_baud_rate);
}

#endif

/*****************************************************************************/
/* SPI 1A Functions                                                           */
/*****************************************************************************/

///////////////////////////////////////////////////////////////////////////////
// Initialize SPI driver
#if defined(drvSPI1A_CONF) && defined(drvSPI1A_BAUD)
void drvSPI1AInit(void)
{
	SPI1ACON = drvSPI1A_CONF; // select mode and enable SPI1
	SPI1ABRG = drvSPI1A_BAUD; // select clock speed
}

///////////////////////////////////////////////////////////////////////////////
// Send and receive one byte over SPI interface
dosByte drvSPI1ASendAndReceiveByte( dosByte in_byte )
{
	SPI1ABUF = in_byte;						// write to buffer for TX
	while ( !SPI1ASTATbits.SPIRBF);	// wait for transfer complete
	return SPI1ABUF;								// read the received value
}

///////////////////////////////////////////////////////////////////////////////
// Sets a new baud rate
void drvSPI1ASetBaudRate(dosDWord in_baud_rate)
{
	SPI1ABRG = SpiBrgVal(sysPBCLK_FREQUENCY, in_baud_rate);
}

///////////////////////////////////////////////////////////////////////////////
// Closes SPI
void drvSPI1ACleanUp(void)
{
	SPI1ACON = 0;
}

///////////////////////////////////////////////////////////////////////////////
// Returns true when SP Iis opened
dosBool drvSPI1AIsOpened(void)
{
	return (SPI1ACONbits.ON != 0);
}

///////////////////////////////////////////////////////////////////////////////
// Send byte (asynchron)
void drvSPI1ASendAsynchronByte( dosByte in_byte )
{
	SPI1ABUF = in_byte;
}

///////////////////////////////////////////////////////////////////////////////
// Receive byte (asynchron)
dosByte drvSPI1AReceiveAsynchronByte(void)
{
	// return result if it's already  in the buffer
	if ( SPI1ASTATbits.SPIRBF != 0 )
		return SPI1ABUF;

	// if SPI is not receiving, return invalid data
	if ( SPI1ASTATbits.SPIBUSY == 0 )
		return 0xff;

	// if SPI is receiving wait for the data to arrive
	while ( !SPI1ASTATbits.SPIRBF);	// wait for transfer complete

	// return data
	return SPI1ABUF;								// read the received value
}

#endif

/*****************************************************************************/
/* SPI 2 Functions                                                           */
/*****************************************************************************/

///////////////////////////////////////////////////////////////////////////////
// Initialize SPI driver
#if defined(drvSPI2_CONF) && defined(drvSPI2_BAUD)
#ifndef _SPI_DEF_CHN_

void drvSPI2Init(void)
{
	SPI2CON = drvSPI2_CONF; // select mode and enable SPI2
	SPI2BRG = drvSPI2_BAUD; // select clock speed
}

///////////////////////////////////////////////////////////////////////////////
// Send and receive one byte over SPI interface
dosByte drvSPI2SendAndReceiveByte( dosByte in_byte )
{
	SPI2BUF = in_byte;						// write to buffer for TX
	while ( !SPI2STATbits.SPIRBF);	// wait for transfer complete
	return SPI2BUF;								// read the received value
}

///////////////////////////////////////////////////////////////////////////////
// Sets a new baud rate
void drvSPI2SetBaudRate(dosDWord in_baud_rate)
{
	SPI2BRG = SpiBrgVal(sysPBCLK_FREQUENCY, in_baud_rate);
}

///////////////////////////////////////////////////////////////////////////////
// Send byte (asynchron)
void drvSPI2SendAsynchronByte( dosByte in_byte )
{
	SPI2BUF = in_byte;
}

///////////////////////////////////////////////////////////////////////////////
// Receive byte (asynchron)
dosByte drvSPI2ReceiveAsynchronByte(void)
{
	// return result if it's already  in the buffer 
	if ( SPI2STATbits.SPIRBF != 0 )
		return SPI2BUF;

	// if SPI is not receiving, return invalid data
	if ( SPI2STATbits.SPIBUSY == 0 )
		return 0;

	// if SPI is receiving wait for the data to arrive
	while ( !SPI2STATbits.SPIRBF);	// wait for transfer complete

	// return data
	return SPI2BUF;								// read the received value
}
#else
///////////////////////////////////////////////////////////////////////////////
//! Initializes SPI2 on PIC32 (drvSPI_CH2_CONF and drvSPI_CH2_BAUD must be defined)
void drvSPI2Init(void)
{
	SpiChnOpen(2, drvSPI2_CONF, drvSPI2_BAUD);
}

///////////////////////////////////////////////////////////////////////////////
//! Sends and receives a byte
//! \param byte to send
//! \param received byte
dosByte drvSPI2SendAndReceiveByte(dosByte in_byte)
{
 volatile _SpiRegMap*  pReg=_SpiMapTbl[2];

	pReg->buf = in_byte;
	while(!_SpiIsRxAvlbl(pReg));  // wait data ready

	return pReg->buf;  // return data in the buffer
}
#endif
#endif

/*****************************************************************************/
/* SPI 2A Functions                                                           */
/*****************************************************************************/

///////////////////////////////////////////////////////////////////////////////
// Initialize SPI driver
#if defined(drvSPI2A_CONF) && defined(drvSPI2A_BAUD)
void drvSPI2AInit(void)
{
	SPI2ACON = drvSPI2A_CONF; // select mode and enable SPI1
	SPI2ABRG = drvSPI2A_BAUD; // select clock speed
}

///////////////////////////////////////////////////////////////////////////////
// Send and receive one byte over SPI interface
dosByte drvSPI2ASendAndReceiveByte( dosByte in_byte )
{
	SPI2ABUF = in_byte;							// write to buffer for TX
	while ( !SPI2ASTATbits.SPIRBF);	// wait for transfer complete
	return SPI2ABUF;								// read the received value
}

///////////////////////////////////////////////////////////////////////////////
// Sets a new baud rate
void drvSPI3SetBaudRate(dosDWord in_baud_rate)
{
	SPI2ABRG = SpiBrgVal(sysPBCLK_FREQUENCY, in_baud_rate);
}
#endif

/*****************************************************************************/
/* SPI 3 Functions                                                           */
/*****************************************************************************/

///////////////////////////////////////////////////////////////////////////////
// Initialize SPI driver
#if defined(drvSPI3_CONF) && defined(drvSPI3_BAUD)
void drvSPI3Init(void)
{
	SPI3CON = drvSPI3_CONF; // select mode and enable SPI1
	SPI3BRG = drvSPI3_BAUD; // select clock speed
}

///////////////////////////////////////////////////////////////////////////////
// Send and receive one byte over SPI interface
dosByte drvSPI3SendAndReceiveByte( dosByte in_byte )
{
	SPI3BUF = in_byte;							// write to buffer for TX
	while ( !SPI3STATbits.SPIRBF);	// wait for transfer complete
	return SPI3BUF;									// read the received value
}

///////////////////////////////////////////////////////////////////////////////
// Sets a new baud rate
void drvSPI3SetBaudRate(dosDWord in_baud_rate)
{
	SPI3BRG = SpiBrgVal(sysPBCLK_FREQUENCY, in_baud_rate);
}
#endif